#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#include "h/queue.h"

#define MIN_PER_HR 60.0

bool newcustomer(double x);
Item customertime(long when);

char * s_gets(char *, int);
void eatline(void);

int main(void)
{
    Queue queue;
    Item tmp;

    unsigned hours;
    unsigned perhour;
    long cycle, cyclelimit;

    long turnaways = 0;
    long customers = 0;
    long served = 0;
    long sum_line  = 0;
    long wait_time = 0;
    double min_per_cust;
    long line_wait = 0;

    InitializeQueue(&queue);
    srand((unsigned) time(NULL));

    puts("Case Study: Sigmund Lander's Advice Booth.");
    puts("Enter the number of simulation hours.");
    scanf("%d", &hours);

    cyclelimit = MIN_PER_HR * hours;

    puts("Enter the average number of customers per hour:");
    scanf("%d", &perhour);

    min_per_cust = MIN_PER_HR / perhour;

    for (cycle = 0; cycle < cyclelimit; ++cycle) {
        if (newcustomer(min_per_cust)) {
            if (QueueIsFull(&queue)) {
                ++turnaways;
            } else {
                ++customers;
                tmp = customertime(cycle);
                EnQueue(tmp, &queue);
            }
        }

        if (wait_time <= 0 && !QueueIsEmpty(&queue)) {
            DeQueue(&tmp, &queue);
            wait_time = tmp.processtime;
            ++served;
            line_wait += cycle - tmp.arrive;
        }

        sum_line += QueueItemCount(&queue);

        if (wait_time > 0)
            --wait_time;

        line_wait+= wait_time;
    }

    if (customers > 0)
    {
        printf("Customers accepted: %ld\n", customers);
        printf(" customers served: %ld\n", served);
        printf("    turnaways: %ld\n", turnaways);
        printf("average queue size: %.2f\n",
                (double) sum_line/cyclelimit);

        printf("average wait time: %2f minutes\n",
                (double) line_wait/served);

    } else
        puts("No customers!");

    EmptyTheQueue(&queue);
    puts("Bye!");

    return 0;
}

bool newcustomer(double x)
{
    if (rand() * x / RAND_MAX < 1)
        return true;
    return false;
}

Item customertime(long when)
{
    Item it;
    it.arrive = when;
    it.processtime = rand() % 3 + 1;

    return it;
}

char * s_gets(char * str, int n)
{
    char * ret_val;
    char * find;

    if ((ret_val = fgets(str, n, stdin))) {
        find = strchr(str, '\n');
        if (find)
            *find = 0;
        else
            while (getchar() != '\n')
                ;
    }

    return ret_val;
}

void eatline(void)
{
    while (getchar() != '\n')
        ;
}
